LL1PRC: PROC;
/****************************************************************
*              LL(1) GRAMMAR ANALYZER - COMMON PROCEDURES	*
*PURPOSE:                                                       *
*    THIS PROGRAM CONTAINS THE COMMON PROCEDURES USES BY        *
*    MOST OF THE OTHER PHASES.					*
*INPUT:                                                         *
*OUTPUT:                                                        *
*OUTLINE:                                                       *
*REMARKS:                                                       *
****************************************************************/

/****************************************************************
* * * * * * * * * * * COMMON DATA DEFINITIONS * * * * * * * * * *
****************************************************************/

/*	* * *  COMMON REPLACEMENTS  * * *	*/
%REPLACE TRUE BY '1'B;
%REPLACE FALSE BY '0'B;

%INCLUDE 'LL1CMN.DCL';	/* GET COMMON AREAS. */

/****************************************************************
* * * * * * * * * * * COMMON PROCUDURES * * * * * * * * * * * * *
****************************************************************/

/********************* CHR_TO_NUM ******************************/
CHRNUM: PROC (L) RETURNS(BIN(15)) EXTERNAL;
/* THIS ROUTINE IS RESPONSIBLE FOR CONVERTING A CHARACTER */
/* TO A BINARY NUMBER. */

     DCL  J BIN(15);               /* LOOP INDEX */
     DCL  K BIT(16);               /* INTERMEDIATE BIT VALUE */
     DCL  L CHAR;                  /* INTERMEDIATE CHAR VALUE */
     DCL  M BIT(8);

     M=UNSPEC(L);
     K='0000'B4;
     SUBSTR(K,9,8)=M;
     UNSPEC(J)=K;

/*   RETURN TO CALLER WITH CHARACTER. */
     RETURN(J);
     END  CHRNUM;


/********************* CLOSURE ******************************/
CLOSUR: PROC(ARRAY_PTR) EXTERNAL;
/*THIS ROUTINE IS RESPONSIBLE FOR CALCULATING THE REFLEXIVE */
/*TRANSITIVE CLOSURE OF THE ARRAY SPECIFIED. */
	DCL I FIXED;		/* INDICES */
	DCL J FIXED;
	DCL K FIXED;
	DCL LIMIT FIXED;
	DCL ARRAY_PTR PTR;

/* PUT IN THE IDENTITY MATRIX. */
	LIMIT=LENGTH(NTRM)+LENGTH(TRM);
	DO I=1 TO LIMIT;
	   CALL SETBIT(I,I,ARRAY_PTR);
	END;

/* COMPUTE THE REFLEXIVE TRANSITIVE CLOSURE. */
	DO I=1 TO LIMIT;
	   DO J=1 TO LIMIT;
	      IF TSTBIT(J,I,ARRAY_PTR) THEN
		 DO K=1 TO LIMIT;
		    IF TSTBIT(J,K,ARRAY_PTR) | TSTBIT(I,K,ARRAY_PTR) THEN
		       CALL SETBIT(J,K,ARRAY_PTR);
		 END;
	   END;
	END;

/* RETURN TO CALLER. */
        END  CLOSUR;


/********************* IS_NTRM ******************************/
ISNTRM: PROC (X) RETURNS(BIT(1)) EXTERNAL;
/* THIS ROUTINE INDICATES IF A VOCABULARY ELEMENT IS */
/* A NON-TERMINAL. */
	DCL X CHAR;		/* INPUT INDEX */
	DCL I FIXED;		/* INTERNAL INDEX */

	IF LENGTH(NTRM)=0 THEN
	   RETURN(FALSE);

	DO I=1 TO LENGTH(NTRM);
	   IF X=SUBSTR(NTRM,I,1) THEN
	      RETURN(TRUE);
	END;

	RETURN(FALSE);
	END ISNTRM;
	

/********************* IS_NLNTRM ******************************/
ISNLNT: PROC (X) RETURNS(BIT(1)) EXTERNAL;
/* THIS ROUTINE INDICATES IF A VOCABULARY ELEMENT IS */
/* A NULLABLE NON-TERMINAL. */
	DCL X CHAR;		/* INPUT INDEX */
	DCL I FIXED;		/* INTERNAL INDEX */

	IF LENGTH(NLNTRM)=0 THEN
	   RETURN(FALSE);

	IF ISNTRM(X)=FALSE THEN /*NOT A NON-TERMINAL*/
	   RETURN(FALSE);

	DO I=1 TO LENGTH(NLNTRM);
	   IF X=SUBSTR(NLNTRM,I,1) THEN
	      RETURN(TRUE);
	END;

	RETURN(FALSE);
	END ISNLNT;
	

/********************* IS_TRM ******************************/
ISTRM: PROC (X) RETURNS(BIT(1)) EXTERNAL;
/* THIS ROUTINE INDICATES IF A VOCABULARY ELEMENT IS TERMINAL. */
	DCL X CHAR;		/* INPUT INDEX */
	DCL I FIXED;		/* INTERNAL INDEX */

	IF LENGTH(TRM)=0 THEN
	   RETURN(FALSE);

	DO I=1 TO LENGTH(TRM);
	   IF X=SUBSTR(TRM,I,1) THEN
	      RETURN(TRUE);
	END;

	RETURN(FALSE);
	END ISTRM;
	

/********************* MULTREL ******************************/
MULREL: PROC EXTERNAL;
/*THIS ROUTINE IS RESPONSIBLE FOR MULTIPLYING TWO RELATION- */
/*SHIPS TOGETHER. */
	DCL I FIXED;		/* INDICES */
	DCL J FIXED;
	DCL K FIXED;
	DCL LIMIT FIXED;
	DCL ARRAY_PTR PTR;
	DCL ARRAY3(256,32) BIT(8) BASED(ARRAY_PTR);

/* DO INITIALIZATION. */
	LIMIT=LENGTH(NTRM)+LENGTH(TRM); /*GET ARRAY SIZE.*/
	ALLOCATE ARRAY3 SET(ARRAY_PTR);
	CALL ZEROAR(ARRAY_PTR);

/* MULTIPLY ARRAY1 BY ARRAY2. */
	DO J=1 TO LIMIT;
	   DO I=1 TO LIMIT;
	      IF TSTBIT(I,J,ADDR(ARRAY1)) THEN
		 DO K=1 TO LIMIT;
		    IF TSTBIT(J,K,ADDR(ARRAY2)) THEN
		       CALL SETBIT(I,K,ARRAY_PTR);
		 END;
	   END;
	END;

/* PUT THE PRODUCT BACK IN ARRAY1. */
	DO I=1 TO LIMIT;
	   DO J=1 TO 32;
	      ARRAY1(I,J)=ARRAY3(I,J);
	   END;
	END;
	FREE ARRAY3;

/* RETURN TO CALLER. */
        END  MULREL;


/********************* NUM_TO_CHR ******************************/
NUMCHR: PROC (J) RETURNS(CHAR) EXTERNAL;
/* THIS ROUTINE IS RESPONSIBLE FOR CONVERTING A BINARY*/
/* NUMBER TO A CHARACTER.*/

     DCL  J BIN(15);               /* LOOP INDEX */
     DCL  K BIT(16);               /* INTERMEDIATE BIT VALUE */
     DCL  L CHAR;                  /* INTERMEDIATE CHAR VALUE */

     UNSPEC(K)=J;
     UNSPEC(L)=SUBSTR(K,8,8);

/*   RETURN TO CALLER WITH CHARACTER. */
     RETURN(L);
     END  NUMCHR;


/********************* PRINT_ARRAY ******************************/
PRTARY: PROC(HEADING,PHS,HORNUM,VERNUM,ARRAY_PTR) EXTERNAL;
/*THIS ROUTINE IS RESPONSIBLE FOR PRINTING THE RELATION */
/*DEFINED BY ARRAY1. */
	DCL I BIN(15);		/* INDEXES */
	DCL J BIN(15);
	DCL COL_FROM FIXED;
	DCL COL_TO FIXED;
	DCL LIN_FROM FIXED;
	DCL LIN_TO FIXED;
	DCL HEADING CHAR(40) VARYING;
	DCL PHS BIT(1);		/* PRINT HORIZONTAL SYMBOL FLAG */
	DCL HORNUM FIXED;	/* NUMBER OF HORIZONTAL LINES */
	DCL VERNUM FIXED;	/* NUMBER OF VERTICAL LINES */
	DCL ARRAY_PTR PTR;

/* PRINT HEADING. */
PRINT_HDNG: PROC(COL_FROM,COL_TO);
	DCL I FIXED;
	DCL J FIXED;
	DCL COL_FROM FIXED;
	DCL COL_TO FIXED;
	DCL LINE_OUT CHAR(130) VARYING;

/* PRINT STANDARD HEADER. */
	PUT FILE(LSTFIL) PAGE;
	PUT FILE(LSTFIL) SKIP(3) 
	    EDIT(HEADING,'PAGE',PAGENO(LSTFIL)-1)
		  (X(15),A(37),X(10),A(4),F(4));
	PUT FILE(LSTFIL) SKIP(1);
	
/* PRINT LINES OF SYMBOL NUMBERS FOR HORIZONTAL. */
	I=100;
	DO WHILE(I>0);
	   LINE_OUT='';
	   DO J=COL_FROM TO COL_TO;
	      IF J<I THEN
		 LINE_OUT=LINE_OUT || ' ';
	      ELSE
		 LINE_OUT=LINE_OUT || ASCII(48+MOD(J/I,10));
	   END;
	   PUT FILE(LSTFIL) SKIP EDIT(LINE_OUT) (X(20),A);
	   I=I/10;
	END;

/* PRINT TOP SEPERATOR LINE. */
	CALL PRINT_SEP(COL_FROM,COL_TO);

/* RETURN TO CALLER. */
	   END PRINT_HDNG;

/* PRINT THE CURRENT LINE. */
PRINT_LINE: PROC(COL_CUR,COL_FROM,COL_TO);
	DCL I FIXED;
	DCL COL_CUR FIXED;
	DCL COL_FROM FIXED;
	DCL COL_TO FIXED;
	DCL LINE_OUT CHAR(130) VARYING;
	DCL SYMBOL CHAR(10) VARYING;

/* BUILD MATRIX PART OF LINE. */
	LINE_OUT='';
	DO I=COL_FROM TO COL_TO;
	   IF TSTBIT(COL_CUR,I,ARRAY_PTR) THEN
	      LINE_OUT=LINE_OUT || '1';
	   ELSE
	      LINE_OUT=LINE_OUT || '0';
	END;

/* PRINT THE LINE. */
	IF PHS THEN
	   SYMBOL=VOC(COL_CUR);
	ELSE
	   SYMBOL='';
	PUT FILE(LSTFIL) SKIP EDIT(COL_CUR,SYMBOL,'|',LINE_OUT,'|')
				 (X(04),F(4),X(01),A(10),A(1),A,A(1));

/* RETURN TO CALLER. */
	   END PRINT_LINE;

PRINT_SEP: PROC(COL_FROM,COL_TO);
	DCL I FIXED;
	DCL J FIXED;
	DCL COL_FROM FIXED;
	DCL COL_TO FIXED;
	DCL LINE_OUT CHAR(130) VARYING;

/* PRINT SEPERATOR LINE. */
	LINE_OUT='+';
	DO I=COL_FROM TO COL_TO;
	   LINE_OUT=LINE_OUT || '-';
	END;
	LINE_OUT=LINE_OUT || '+';
	PUT FILE(LSTFIL) SKIP EDIT(LINE_OUT) (X(19),A);

/* RETURN TO CALLER. */
	   END PRINT_SEP;

/* OUTPUT THE HEADING. */
	ON ENDPAGE(LSTFIL)
	   BEGIN;
	      CALL PRINT_HDNG(COL_FROM,COL_TO);
	   END;

/* PRINT THE REPORT PAGE. */
	LIN_FROM=1;		/* SET MARGINS. */
	DO WHILE(LIN_FROM<HORNUM);  /* PRINT HORIZONTAL LINES. */
	   LIN_TO=MIN(HORNUM,55+LIN_FROM);
	   COL_FROM=1;
	   DO WHILE(COL_FROM<VERNUM); /* PRINT VERTICAL LINES. */
	      COL_TO=MIN(VERNUM,55+COL_FROM);
	      SIGNAL ENDPAGE(LSTFIL);
	      DO I=LIN_FROM TO LIN_TO;	/* PRINT THE PAGE. */
	         CALL PRINT_LINE(I,COL_FROM,COL_TO);
	      END;
	      CALL PRINT_SEP(COL_FROM,COL_TO);
	      COL_FROM=COL_FROM+56;
	   END;
	   LIN_FROM=LIN_FROM+56;
	END;

/* RETURN TO CALLER. */
        END  PRTARY;


/********************* RESET_BIT ******************************/
RSTBIT: PROC(X,Y,ARRAY_PTR) EXTERNAL;
/*THIS ROUTINE IS RESPONSIBLE FOR RESETING ON THE BIT DENOTED */
/*BY THE X,Y COORDINATES IN THE ARRAY SPECIFIED. */
	DCL I FIXED;		/* INDICES */
	DCL J FIXED;
	DCL K FIXED;
	DCL X BIN(15);		/* INDICES */
	DCL Y BIN(15);
	DCL ARRAY_PTR PTR;
	DCL ARRAY(256,32) BIT(8) BASED(ARRAY_PTR);

/* DEVELOP ACTUAL ARRAY ELEMENT USING X,Y COORDINATES. */
	I=X;			/* VERTICAL */
	J=(Y/8)+1;		/* HORIZONTAL - BYTE */
	K=MOD(Y,8)+1;		/* HORIZONTAL - BIT */

/* SET THE BIT IN THE ARRAY. */
	SUBSTR(ARRAY(I,J),K,1)=FALSE;

/* RETURN TO CALLER. */
        END  RSTBIT;


/********************* RESTORE_ARRAY ******************************/
RSTARY: PROC(ARRAY_PTR,FILE_TYPE) EXTERNAL;
/* THIS ROUTINE IS RESPONSIBLE FOR RESTORING AN ARRAY. */
	DCL I FIXED;		/* INDICES */
	DCL J FIXED;
	DCL BW_FILE FILE;
	DCL FILE_TYPE CHAR(3);
	DCL FILE_NAME CHAR(20) VARYING;
	DCL ARRAY_PTR PTR;
	DCL ARRAY(64) CHAR(128) BASED(ARRAY_PTR);

/* OPEN THE FILE. */
	FILE_NAME='$1.'||FILE_TYPE;
        OPEN FILE(BW_FILE) DIRECT INPUT TITLE(FILE_NAME)
	     ENV(F(128));

/* WRITE THE ARRAY TO IT. */
	DO I=0 TO 63;
	   READ FILE(BW_FILE) INTO(ARRAY(I+1)) KEY(I);
	END;

/* SAVE THE FILE. */
	CLOSE FILE(BW_FILE);

/* RETURN TO CALLER. */
        END  RSTARY;


/********************* SAVE_ARRAY ******************************/
SAVARY: PROC(ARRAY_PTR,FILE_TYPE) EXTERNAL;
/* THIS ROUTINE IS RESPONSIBLE FOR SAVING AN ARRAY. */
	DCL I FIXED;		/* INDICES */
	DCL J FIXED;
	DCL BW_FILE FILE;
	DCL FILE_TYPE CHAR(3);
	DCL FILE_NAME CHAR(20) VARYING;
	DCL ARRAY_PTR PTR;
	DCL ARRAY(64) CHAR(128) BASED(ARRAY_PTR);

/* OPEN THE FILE. */
	FILE_NAME='$1.'||FILE_TYPE;
        OPEN FILE(BW_FILE) DIRECT OUTPUT TITLE(FILE_NAME)
	     ENV(F(128));

/* WRITE THE ARRAY TO IT. */
	DO I=0 TO 63;
	   WRITE FILE(BW_FILE) FROM(ARRAY(I+1)) KEYFROM(I);
	END;

/* SAVE THE FILE. */
	CLOSE FILE(BW_FILE);

/* RETURN TO CALLER. */
        END  SAVARY;


/********************* SET_BIT ***************************/
SETBIT: PROC(X,Y,ARRAY_PTR) EXTERNAL;
/*THIS ROUTINE IS RESPONSIBLE FOR SETING ON THE BIT DENOTED */
/*BY THE X,Y COORDINATES IN THE ARRAY SPECIFIED. */
	DCL I FIXED;		/* INDICES */
	DCL J FIXED;
	DCL K FIXED;
	DCL X BIN(15);		/* INDICES */
	DCL Y BIN(15);
	DCL ARRAY_PTR PTR;
	DCL ARRAY(256,32) BIT(8) BASED(ARRAY_PTR);

/* DEVELOP ACTUAL ARRAY ELEMENT USING X,Y COORDINATES. */
	I=X;			/* VERTICAL */
	J=(Y/8)+1;		/* HORIZONTAL - BYTE */
	K=MOD(Y,8)+1;		/* HORIZONTAL - BIT */

/* SET THE BIT IN THE ARRAY. */
	SUBSTR(ARRAY(I,J),K,1)=TRUE;

/* RETURN TO CALLER. */
        END  SETBIT;


/********************* TEST_BIT ***************************/
TSTBIT: PROC(X,Y,ARRAY_PTR) RETURNS(BIT(1)) EXTERNAL;
/*THIS ROUTINE IS RESPONSIBLE FOR TESTING THE BIT DENOTED */
/*BY THE X,Y COORDINATES IN THE ARRAY SPECIFIED. */
	DCL I FIXED;		/* INDICES */
	DCL J FIXED;
	DCL K FIXED;
	DCL X BIN(15);		/* INDICES */
	DCL Y BIN(15);
	DCL ARRAY_PTR PTR;
	DCL ARRAY(256,32) BIT(8) BASED(ARRAY_PTR);

/* DEVELOP ACTUAL ARRAY ELEMENT USING X,Y COORDINATES. */
	I=X;			/* VERTICAL */
	J=(Y/8)+1;		/* HORIZONTAL - BYTE */
	K=MOD(Y,8)+1;		/* HORIZONTAL - BIT */

/* RETURN THE BIT IN THE ARRAY. */
	RETURN(SUBSTR(ARRAY(I,J),K,1));

/* RETURN TO CALLER. */
        END  TSTBIT;


/********************* ZERO_ARRAY ***************************/
ZEROAR: PROC(ARRAY_PTR) EXTERNAL;
/*THIS ROUTINE IS RESPONSIBLE FOR ZEROING THE ARRAY SPECIFIED. */
	DCL I FIXED;		/* INDICES */
	DCL J FIXED;
	DCL ARRAY_PTR PTR;
	DCL ARRAY(256,32) BIT(8) BASED(ARRAY_PTR);

/* ZERO THE ARRAY. */
	DO I=1 TO 256;
	   DO J=1 TO 32;
	      ARRAY(I,J)='00000000'B;
	   END;
	END;

/* RETURN TO CALLER. */
        END  ZEROAR;


/****************************************************************
* * * * * * * * * * * MAIN ROUTINE  * * * * * * * * * * * * * * *
****************************************************************/

	END LL1PRC;
